package com.superb.system.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.superb.common.core.annotation.SuperbDataScope;
import com.superb.common.core.annotation.SuperbRestMapping;
import com.superb.common.core.enums.SuperbCode;
import com.superb.common.core.exception.SuperbException;
import com.superb.common.core.model.Result;
import com.superb.common.redis.key.KeyType;
import com.superb.common.redis.key.RedisKey;
import com.superb.common.redis.utils.RedisUtils;
import com.superb.common.utils.HeardersUtils;
import com.superb.common.utils.StringUtils;
import com.superb.system.api.dto.UserInfo;
import com.superb.system.api.entity.SystemUser;
import com.superb.system.api.vo.UpdateAccount;
import com.superb.system.api.vo.UpdateCurrent;
import com.superb.system.service.SystemUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @Author: ajie
 * @CreateTime: 2024-07-03 10:47
 */
@Tag(name = "当前用户")
@SuperbRestMapping("current/user")
@ApiSupport(author = "ajie: ajie20999@163.com", order = 2)
public class CurrentUserController {

    @Resource
    private SystemUserService userService;


    @GetMapping
    @SuperbDataScope
    @ApiOperationSupport(order = 1)
    @Operation(summary = "当前登录用户信息", description = "根据当前登录人获取缓存信息")
    public Result<UserInfo> userInfo(@RequestParam(required = false, defaultValue = "") String scopeId) {
        return Result.success(userService.getCurrentUser(scopeId));
    }

    @PostMapping("updateBase")
    @ApiOperationSupport(order = 2)
    @Operation(summary = "修改本人基础信息")
    public Result<Boolean> updateAvatar(@RequestBody @Validated UpdateCurrent current) {
        String userId = StpUtil.getLoginId().toString();
        SystemUser user = BeanUtil.copyProperties(current, SystemUser.class);
        user.setId(userId);
        if (StringUtils.isNotBlank(current.getPhoneNumber())) {
            if (userService.count(Wrappers.<SystemUser>lambdaQuery()
                    .eq(SystemUser::getPhoneNumber, current.getPhoneNumber())
                    .ne(SystemUser::getId, userId)
                    .eq(SystemUser::getTenantId, HeardersUtils.getTenantId())) > 0) {
                return Result.error("当前手机号已注册！");
            }
        }
        if (StringUtils.isNotBlank(current.getIdcard())) {
            if (userService.count(Wrappers.<SystemUser>lambdaQuery()
                    .eq(SystemUser::getPhoneNumber, current.getIdcard())
                    .ne(SystemUser::getId, userId)
                    .eq(SystemUser::getTenantId, HeardersUtils.getTenantId())) > 0) {
                return Result.error("当前身份证号已被使用！");
            }
        }
        if (StringUtils.isNotBlank(current.getEmail())) {
            if (userService.count(Wrappers.<SystemUser>lambdaQuery()
                    .eq(SystemUser::getPhoneNumber, current.getEmail())
                    .ne(SystemUser::getId, userId)
                    .eq(SystemUser::getTenantId, HeardersUtils.getTenantId())) > 0) {
                return Result.error("当前邮箱地址已被使用！");
            }
        }
        if (userService.updateById(user)) {
            RedisKey key = new RedisKey(KeyType.TIME, "userCache:" + userId);
            RedisUtils.build().del(key);
            return Result.success();
        }
        return Result.error();
    }

    @PostMapping("updateAccount")
    @ApiOperationSupport(order = 3)
    @Operation(summary = "修改本人登录账号")
    public Result<Boolean> updateAccount(@RequestBody @Validated(value = UpdateAccount.Username.class) UpdateAccount account) {
        String userId = StpUtil.getLoginId().toString();
        SystemUser user = userService.getInfoById(userId);
        String salt = user.getSalt();
        String password = salt + account.getPassword();
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(password, user.getPassword())) {
            throw new SuperbException(SuperbCode.LOGIN_USER_PASSWORD);
        }
        SystemUser systemUser = new SystemUser();
        systemUser.setId(userId);
        systemUser.setUsername(account.getUsername());
        if (userService.updateById(systemUser)) {
            RedisKey key = new RedisKey(KeyType.TIME, "userCache:" + userId);
            RedisUtils.build().del(key);
            return Result.success();
        }
        return Result.error();
    }

    @PostMapping("updatePassword")
    @ApiOperationSupport(order = 3)
    @Operation(summary = "修改本人登录密码")
    public Result<Boolean> updatePassword(@RequestBody @Validated(value = UpdateAccount.Password.class) UpdateAccount account) {
        String userId = StpUtil.getLoginId().toString();
        SystemUser user = userService.getInfoById(userId);
        String salt = user.getSalt();
        String password = salt + account.getPassword();
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(password, user.getPassword())) {
            return Result.error("旧密码错误，请检查后输入！");
        }
        SystemUser systemUser = new SystemUser();
        systemUser.setId(userId);
        // 10位随机数，作为登录密码的秘钥
        String newSalt = RandomStringUtils.random(10, "SuperbAjiez01654+/=*");
        systemUser.setPassword(encoder.encode(newSalt + account.getNewPassword()));
        systemUser.setSalt(newSalt);
        if (userService.updateById(systemUser)) {
            RedisKey key = new RedisKey(KeyType.TIME, "userCache:" + userId);
            RedisUtils.build().del(key);
            return Result.success();
        }
        return Result.error();
    }

}
